package com.xunyji.demo02weixinauthorization.web.thymeleaf;

import com.xunyji.demo02weixinauthorization.comm.config.weixin.WeixinBaseInfoProperties;
import com.xunyji.demo02weixinauthorization.comm.util.HttpUtils;
import com.xunyji.demo02weixinauthorization.comm.util.TransformUtils;
import com.xunyji.demo02weixinauthorization.model.weixin.GetAuthAccessTokenResponse;
import com.xunyji.demo02weixinauthorization.model.weixin.GetUserInfoResponse;
import com.xunyji.demo02weixinauthorization.model.weixin.UserBindDO;
import com.xunyji.demo02weixinauthorization.repository.UserBindRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.xml.TransformerUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author AltEnter
 * @create 2019-01-13 14:32
 * @desc 微信相关的页面控制类
 **/
@Controller
@Slf4j
@RequestMapping(value = "/weixin")
public class WeixinThymeleafController {

    /** 微信先关配置信息 */
    @Autowired
    private WeixinBaseInfoProperties weixinBaseInfoProperties;
    /** HTTP请求方法工具类 */
    @Autowired
    private HttpUtils httpUtils;
    /** 对象转换工具类 */
    @Autowired
    private TransformUtils transformerUtils;

    @Autowired
    private UserBindRepository userBindRepository;

    @GetMapping(value = "/connect")
    public String connect (ModelMap map) {
        String msg = "微信页面测试";
        log.info(msg);
        map.addAttribute("msg", msg);
        return "connect";
    }

    @GetMapping(value = "/index")
    public String toIndex (ModelMap map) {
        log.info("去往主页......");
        return "index";
    }

    /**
     * 微信网页授权逻辑入口
     * @param map
     */
    @GetMapping(value = "/auth")
    public void toAuth(ModelMap map, HttpServletRequest request, HttpServletResponse response) throws IOException {
        log.info("进入微信授权逻辑......");
//        微信网页授权第一步 - 用户同意授权，获取code - start
        String getCodeUrl = weixinBaseInfoProperties.getAuth().getGetCodeUrl();
        String appid = weixinBaseInfoProperties.getAppid();
        String appsecret = weixinBaseInfoProperties.getAppsecret();
        String redirectUri = weixinBaseInfoProperties.getAuth().getRedirectUri();
        String scope = weixinBaseInfoProperties.getAuth().getScope();
        getCodeUrl = getCodeUrl.replace("APPID", appid)
                .replace("REDIRECT_URI", redirectUri)
                .replace("SCOPE", scope);
        log.info("封装好的getCodeUrl为：" + getCodeUrl);
        response.sendRedirect(getCodeUrl);
//        微信网页授权第一步 - 用户同意授权，获取code - end
    }

    /**
     * 回调页面
     * @param map
     * @return
     */
    @GetMapping(value = "/callback")
    public String callback(ModelMap map, HttpServletRequest request, HttpServletResponse response) {
        log.info("进入回调处理逻辑......");
        String appid = weixinBaseInfoProperties.getAppid();
        String appsecret = weixinBaseInfoProperties.getAppsecret();

//        微信网页授权第二步 - 通过code换取网页授权access_token - start
        StringBuffer requestURL = request.getRequestURL();
        log.info("进入回调处理逻辑的请求url为：" + requestURL);
        String code = request.getParameter("code");
        log.info("获取到的用于换取access_token的票据的code值为：" + code);

        String getAccessTokenUrl = weixinBaseInfoProperties.getAuth().getGetAccessTokenUrl();
        getAccessTokenUrl = getAccessTokenUrl.replace("APPID", appid)
                .replace("SECRET", appsecret)
                .replace("CODE", code);
        log.info("封装好的用于获取accessToke的url为：" + getAccessTokenUrl);
        String getAccessTokenResponseStr = httpUtils.doGetStrByRestTemplate(getAccessTokenUrl);
        log.info("发送获取access_token请求后的响应为STR：" + getAccessTokenResponseStr);
        GetAuthAccessTokenResponse getAuthAccessTokenResponse = transformerUtils.String2Object(getAccessTokenResponseStr, GetAuthAccessTokenResponse.class);
        log.info("发送获取access_token请求后的响应为：" + getAuthAccessTokenResponse);
        String access_token = getAuthAccessTokenResponse.getAccess_token();
        String open_id = getAuthAccessTokenResponse.getOpenid();
//        微信网页授权第二步 - 通过code换取网页授权access_token - end

//        微信网页授权第四步 - 拉取用户信息(需scope为 snsapi_userinfo) - start
        String getUserInfoUrl = weixinBaseInfoProperties.getAuth().getGetUserInfoUrl();
        getUserInfoUrl = getUserInfoUrl.replace("ACCESS_TOKEN", access_token)
                .replace("OPENID", open_id);
        log.info("封装好的用于获取userInfo的url为：" + getUserInfoUrl);
        String getUserInfoResponseStr = httpUtils.doGetStrByRestTemplate(getUserInfoUrl);
        log.info("发送获取userInfo请求后的响应为STR：" + getUserInfoResponseStr);
        GetUserInfoResponse getUserInfoResponse = transformerUtils.String2Object(getUserInfoResponseStr, GetUserInfoResponse.class);
        log.info("发送获取userInfo请求后的响应为：" + getUserInfoResponse);
//        微信网页授权第四步 - 拉取用户信息(需scope为 snsapi_userinfo) - end

//        第一种使用：直接使用微信的用户用户体系
//        map.addAttribute("userinfo", getUserInfoResponse);
//        return "index2";

//        第二种：微信用户和网站用户进行绑定
//        根据openid查询网站的账户信息
        UserBindDO userBindDOByOpenid = userBindRepository.findByOpenid(getUserInfoResponse.getOpenid());
        if (userBindDOByOpenid != null) {
//            已经绑定过的情况
            log.info("已经绑定过啦");
            map.addAttribute("userinfo", userBindDOByOpenid);
            return "index3";
        } else {
//            没有绑定过的情况
            log.info("还未进行绑定操作");
            map.addAttribute("openid", getUserInfoResponse.getOpenid());
            map.addAttribute("nickname", getUserInfoResponse.getNickname());
            return "login";
        }
    }

    @PostMapping(value = "/login")
    public String login(UserBindDO userBindDO, ModelMap map) {
        log.info("获取到的参数信息为：" + userBindDO);
//        TODO: 对账户信息进行格式校验，如果格式不正确直接返回登录绑定页面
//        TODO: 验证账户是否存在, 如果不存在直接跳转到注册页面（微信用户信息同时返回），在注册逻辑中直接进行绑定
//        TODO: 验证账户密码是否正确，如果部正确直接返回登录绑定页面
        UserBindDO save = userBindRepository.save(userBindDO);
        if (save != null) {
            log.info("bind - 绑定成功");
            log.info("绑定后的结果信息为：" + save);
            map.addAttribute("userinfo", save);
            return "index3";
        } else {
            log.info("bind - 绑定失败");
            return "login";
        }
    }
    
}

